package com.start.workflow.core.manage;

import com.alibaba.fastjson2.JSONObject;
import com.start.common.entity.StartDicData;
import com.start.common.exceptions.StartBusException;
import com.start.common.std.StartBaseSingleton;
import com.start.common.std.StartSingletonFactory;
import com.start.common.tools.SpringContextTools;
import com.start.workflow.common.StartActBusForm;
import com.start.workflow.common.enums.StartActHandlerStatus;
import com.start.workflow.common.model.StartActConfigModel;
import com.start.workflow.common.std.IStartActFormStore;
import com.start.workflow.entity.StartActModelConfig;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.*;

@Slf4j
 @Schema(name="StartActFormManager", description = "流程表单管理器")
public class StartActFormManager extends StartBaseSingleton<StartActFormManager> {

    private LinkedHashMap<String, IStartActFormStore> startActFormMap;
    private static final String REDIS_KEY_PREFIX = "start:act:form";


    /**
     * 处死化加载全部任务候选人加载器
     */
    public void init() {

        startActFormMap = new LinkedHashMap<>();
        Map<String, IStartActFormStore> beans = SpringContextTools.getBeans(IStartActFormStore.class, false);
        if (beans == null || beans.isEmpty()) return;
        for (IStartActFormStore load : beans.values()) {
            String actFormType = load.actFormType();
            if (StringUtils.isAllBlank(actFormType)) {
                log.error(load.getClass().getName() + " 未定义 actFormType");
                continue;
            }
            if (startActFormMap.containsKey(actFormType)) {
                IStartActFormStore old = startActFormMap.get(actFormType);
                log.error(old.getClass().getName() + "," + load.getClass().getName() + "重复类型表单配置加载：" + actFormType);
                continue;
            }
            startActFormMap.put(actFormType, load);
        }
    }

    /**
     * 获取当前实例
     *
     * @return
     */
    public static StartActFormManager getInstance() {
        return StartSingletonFactory.get(StartActFormManager.class);
    }

    /**
     * 加载表单配置
     *
     * @param config 模型配置
     * @return
     */
    public JSONObject loadOption(StartActConfigModel config) {
        IStartActFormStore startActForm = getStartBaseActForm(config.getConfKey());
        return startActForm.loadOption(config);
    }

    /**
     * 删除流程表单数据
     *
     * @param modelConfig
     * @param procInstId
     */
    public void delProcFormData(StartActConfigModel modelConfig, String procInstId) {
        IStartActFormStore startActForm = getStartBaseActForm(modelConfig.getConfKey());
        startActForm.delProcFormData(modelConfig, procInstId);

    }


    /**
     * 删除流程流程用户任务表单数据
     *
     * @param modelConfig
     * @param procInstId
     */
    public void delProcTaskFormData(StartActConfigModel modelConfig, String procInstId, String taskInstId) {
        IStartActFormStore startActForm = getStartBaseActForm(modelConfig.getConfKey());
        startActForm.delProcTaskFormData(modelConfig, procInstId, taskInstId);
    }

    /**
     * 保存流程数据
     *
     * @param modelConfig 流程表单配置key
     * @param procInstId  流程实例id
     * @param status      当前流程实例状态
     * @param data        需要保存的数据
     * @return 返回数据id
     */
    public String saveProcData(StartActConfigModel modelConfig, String procInstId, StartActHandlerStatus status, JSONObject data) {
        IStartActFormStore startActForm = getStartBaseActForm(modelConfig.getConfKey());
        data.put(StartActBusForm.ProcCol.PROCESS_DEFINITION_KEY, modelConfig.getProcDefKey());
        data.put(StartActBusForm.ProcCol.PROCESS_STATE, status.getValue());
        data.put(StartActBusForm.ProcCol.PROCESS_INSTANCE_ID, procInstId);

        String rowId = startActForm.saveProcFormData(modelConfig, procInstId, status, data);
        if (StringUtils.isAllBlank(rowId)) {
            throw new StartBusException("需要返回数据id");
        }
        return rowId;
    }

    /**
     * 保存流程数据
     *
     * @param modelConfig 流程表单配置key
     * @param procInstId  流程实例id
     * @return 返回数据id
     */
    public JSONObject getProcFormData(StartActConfigModel modelConfig, String procInstId) {
        IStartActFormStore startActForm = getStartBaseActForm(modelConfig.getConfKey());
        return startActForm.getProcFormData(modelConfig, procInstId);
    }

    /**
     * 保存流程任务数据
     *
     * @param modelConfig 模型配置
     * @param procInstId  流程实例id
     * @param taskInstId  任务实例id
     * @param status      流程任务状态
     * @param data        需要保存的诗句
     * @return
     */
    public String saveProcTaskData(StartActConfigModel modelConfig, String procInstId, String taskInstId, StartActHandlerStatus status, JSONObject data) {
        IStartActFormStore startActForm = getStartBaseActForm(modelConfig.getConfKey());
        data.put(StartActBusForm.ProcCol.PROCESS_DEFINITION_KEY, modelConfig.getProcDefKey());
        data.put(StartActBusForm.ProcCol.PROCESS_STATE, status.getValue());
        data.put(StartActBusForm.ProcCol.PROCESS_INSTANCE_ID, procInstId);
        data.put(StartActBusForm.ProcTaskCol.PROCESS_TASK_DEF_KEY, modelConfig.getProcDefKey());
        data.put(StartActBusForm.ProcTaskCol.PROCESS_TASK_INST_ID, taskInstId);
        data.put(StartActBusForm.ProcTaskCol.PROCESS_TASK_STATE_KEY, status.getValue());
        String rowId = startActForm.saveProcTaskFormData(modelConfig, procInstId, taskInstId, status, data);
        if (StringUtils.isAllBlank(rowId)) {
            throw new StartBusException("需要返回数据id");
        }
        return rowId;
    }

    public long countProcTaskDataByDefKey(StartActConfigModel modelConfig, String procInstId, String taskDefKey) {
        IStartActFormStore startActForm = getStartBaseActForm(modelConfig.getConfKey());
        return startActForm.countProcTaskDataByDefKey(modelConfig, procInstId, taskDefKey);
    }

    /**
     * 获取流程任务数据
     *
     * @param modelConfig 流程模型配置
     * @param procInstId  流程实例id
     * @param taskInstId  任务实例id
     * @return
     */
    public JSONObject geProcTaskData(StartActConfigModel modelConfig, String procInstId, String taskInstId) {
        IStartActFormStore startActForm = getStartBaseActForm(modelConfig.getConfKey());
        return startActForm.getProcTaskFormData(modelConfig, procInstId, taskInstId);
    }

    /**
     * 加载表单配置
     *
     * @param config
     * @return
     */
    public static JSONObject loadFormOption(StartActConfigModel config) {
        return getInstance().loadOption(config);
    }

    /**
     * 获取全部表单类型加载器
     *
     * @return
     */
    public List<StartDicData> getDicLoad() {
        List<StartDicData> result = new ArrayList<>();
        Collection<IStartActFormStore> values = startActFormMap.values();
        for (IStartActFormStore load : values) {
            result.add(new StartDicData(load.actFormTypeLabel(), load.actFormType()));
        }
        return result;
    }

    /**
     * 流程状态变化监听
     *
     * @param actModelConfig 模型配置
     * @param status         流程状态
     * @param procInstId     流程实例id
     */
    public void onActStateChange(StartActConfigModel actModelConfig, StartActHandlerStatus status, String procInstId) {
        IStartActFormStore startActForm = getStartBaseActForm(actModelConfig.getConfKey());
        try {
            startActForm.onActProcStateChange(actModelConfig, status, procInstId);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 流程状态变化监听
     *
     * @param modelConfig 模型配置
     * @param status      流程状态
     * @param procInstId  流程实例id
     * @param taskInstId  任务id
     */
    public void onActProcTaskStateChange(StartActConfigModel modelConfig, StartActHandlerStatus status, String procInstId, String taskInstId) {
        IStartActFormStore startActForm = getStartBaseActForm(modelConfig.getConfKey());
        try {
            startActForm.onActProcTaskStateChange(modelConfig, status, procInstId, taskInstId);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 删除指定流程实例自定任务定义key数据
     *
     * @param config     配置
     * @param procInstId 流程实例id
     * @param taskDefKey 流程定义key
     * @return
     */
    public long delProcTaskDataByDefKey(StartActModelConfig config, String procInstId, String taskDefKey) {
        IStartActFormStore startActForm = getStartBaseActForm(config.getConfKey());
        return startActForm.delProcTaskDataByDefKey(config, procInstId, taskDefKey);
    }

    private IStartActFormStore getStartBaseActForm(String formKey) {
        if (!startActFormMap.containsKey(formKey)) {
            throw new StartBusException("未找到：" + formKey + "类型的表单配置加载器");
        }
        return startActFormMap.get(formKey);
    }


}
